<?php
/**
 * twitter.inc
 * Widget to display a twitter feed.
 * @copyright	Copyright(c) 2002-2010 Bjorn Winberg
 * @author		Bjorn Winberg <cms@anomalye.net>
 * @license		http://www.gnu.org/licenses/gpl.html GNU General Public License version 2
 * @package		AnomalyWiki
 */
  
class Twitter extends Module{
	public static $MODULE_UID = 'twitter';
	const SQL_TABLE_TWEETS = 'CREATE TABLE IF NOT EXISTS twitter_items (uid TEXT PRIMARY KEY, timestamp INTEGER, added_timestamp TEXT, author TEXT, content TEXT)';
	const PARAM_MAX_ACTION = 64;
	const PARAM_MAX_NAME = 16;
	const PARAM_MAX_COUNT = 100;
	protected $mSystem;	
	
	/**
	 *
	 */
	public function __construct(){
		parent::__construct();
		$this->loadSettings();
		$this->mSystem = ModuleFactory::loadModule('system');	
	}
	
	/**
	 *
	 */
	public function generateView(){
		$params = array();
		$db = ModuleFactory::getDb();
		$inputAction = $this->getParamEnc('a', 1, self::PARAM_MAX_ACTION);
		if($inputAction === 'widgetlist'){
			$this->mSystem->mOutputMode = SystemModule::OUTPUT_TEXT;
			$inputUserName = $this->getParamUId('name', 1, self::PARAM_MAX_NAME);
			$inputCount = $this->getParamEnc('count', 1, self::PARAM_MAX_COUNT, $this->localSetting('PARSE_DEFAULT_LIST_LENGTH'));
			if($this->isCacheTooOld($db, $inputUserName)){
				$feed = $this->twitterUserTimeline(array('screen_name' => $inputUserName, 'count' => $this->localSetting('API_REQUEST_COUNT')));
				$this->writeFeedItems($db, $inputUserName, $feed);
			}
			$params['tweetList'] = $this->readFeedItems($db, $inputUserName, $inputCount);
			return $this->generateTemplate('twitter_widget_list.inc', $params);
		}
	}
	
	/**
	 *
	 */
	public function firstTimeSetup(){
		$db = ModuleFactory::getDb();
		$db->dbExecute(self::SQL_TABLE_TWEETS);
	}
	
	/**
	 *
	 */
	public function handleParseTag($aParser, $aTag){
		$tagBits = explode(rawurlencode($this->mSystem->localSetting('COMMAND_PARAMETER_SEPARATOR')), $aTag);
		$db = ModuleFactory::getDb();
		if($tagBits[1] == rawurlencode('twitter')){
			if(isset($tagBits[2])){
				$userName = strtolower($tagBits[2]);
				$ajaxUId = $aParser->getAjaxUId();
				$listLength = isset($tagBits[3]) && is_numeric($tagBits[3])? (int)$tagBits[3]: $this->localSetting('PARSE_DEFAULT_LIST_LENGTH');
				$params['tweetList'] = $this->readFeedItems($db, $userName, $listLength);
				$parsed = $this->generateTemplate('twitter_widget_list.inc', $params);
				$twitterDiv = '<div id="' . $ajaxUId . '">' . $parsed . '</div>';
				$requestUrl = $this->generateUrl('twitter', $aParams = array('a' => 'widgetlist', 'name' => $userName, 'count' => $listLength), '&');
				$this->mSystem->mHtmlHeaders[] = $this->generateJavascriptWrapper('addLoadEvent(ajax_xmlHttpSend("' . $requestUrl . '", "' . $ajaxUId . '"))', false);
				return $twitterDiv;
			}
		}
		else{
			$this->mSystem->feedbackWarn($this->mSystem->localString('PARSE_INVALID_VARIABLE', array($this->getSafeStr($tagBits[1]))));
		}
	}
	
	/**
	 *
	 */
	public function linkifyTwitterTags($aText){
		$aText = preg_replace('/(https?:\/\/\S+)/', '<a href="\1">\1</a>', $aText);
		$aText = preg_replace('/(^|\s)@(\w+)/', '\1@<a href="http://twitter.com/\2">\2</a>', $aText);
		$aText = preg_replace('/(^|\s)#(\w+)/', '\1#<a href="http://search.twitter.com/search?q=%23\2">\2</a>', $aText);
		return $aText;
	}
	
	/**
	 *
	 */
	public function readFeedItems($aDb, $aName, $aListLength){
		$tweetList = array();
		$result = $aDb->dbQuery('SELECT * FROM twitter_items WHERE author=\'' . $aDb->dbEscape($aName) . '\' ORDER BY timestamp DESC LIMIT ' . $aListLength);
		while($row = $result->fetchArray(SQLITE3_ASSOC)){ 
			$tweetList[] = $row;
		}
		return $tweetList;
	}
	
	/**
	 *
	 */
	public function writeFeedItems($aDb, $aAuthor, $aFeed){
		if($aFeed !== false){
			foreach($aFeed as $index => $entry){
				if(isset($entry->text) && isset($entry->created_at) && isset($entry->id_str)){
					$status = $entry->text;
					$uid = $entry->id_str;
					$timestamp = $entry->created_at;
					$timestamp = strtotime($timestamp);
					$dbValues = array('uid' => $uid, 'timestamp' => $timestamp, 'added_timestamp' => time(), 'author' => $aAuthor, 'content' => $status);
					$aDb->dbExecute('REPLACE INTO twitter_items' . $aDb->dbValues($dbValues));
				}
			}
		}
	}

	/**
	 *
	 */
	function isCacheTooOld($aDb, $aName){
		$result = $aDb->dbQuery('SELECT * FROM twitter_items WHERE author=\'' . $aDb->dbEscape($aName) . '\' ORDER BY added_timestamp DESC LIMIT 1');
		if($row = $result->fetchArray(SQLITE3_ASSOC)){
			$timeDiff = time() - $row['added_timestamp'];
			return $timeDiff > $this->localSetting('MIN_UPDATE_SECS');
		}
		return true;
	}
	
	/**
	* Reference: https://dev.twitter.com/docs/auth/creating-signature
	*/
	function twitterUserTimeline($aParameters = array()){
		$host = 'api.twitter.com';
		$document = '/1.1/statuses/user_timeline.json';
		$url = 'https://' . $host . $document;
		
		$oauth['oauth_consumer_key'] = $this->localSetting('OAUTH_CONSUMER_KEY');
		$oauth['oauth_nonce'] = time();
		$oauth['oauth_signature_method'] = 'HMAC-SHA1';
		$oauth['oauth_token'] = $this->localSetting('OAUTH_ACCESS_TOKEN');
		$oauth['oauth_timestamp'] = time();
		$oauth['oauth_version'] = '1.0';
		$requestParameters = array();
		foreach($aParameters as $key => $value){
			$oauth[$key] = $value;
			$requestParameters[] = $key . '=' . $value;
		}
		$oauthParameters = array(); 
		ksort($oauth); 
		foreach($oauth as $key => $value){ 
			$oauthParameters[] = "$key=" . rawurlencode($value); 
		} 
		$baseInfo =  "GET&" . rawurlencode($url) . '&' . rawurlencode(implode('&', $oauthParameters)); 
		$compositeKey = rawurlencode($this->localSetting('OAUTH_CONSUMER_SECRET')) . '&' . rawurlencode($this->localSetting('OAUTH_ACCESS_TOKEN_SECRET')); 
		$signature = base64_encode(hash_hmac('sha1', $baseInfo, $compositeKey, true)); 
		$oauth['oauth_signature'] = $signature;
		$authHeader = 'Authorization: OAuth '; 
		$values = array(); 
		foreach($oauth as $key=>$value){
			$values[] = "$key=\"" . rawurlencode($value) . "\"";
		}
		$authHeader .= implode(', ', $values);

		$path = $requestParameters != array()? $document . '?' . implode('&', $requestParameters): $document;
		$json = $this->httpRequest($host, $path, '', 'GET', array($authHeader), true);
		$twitterJson = json_decode($json);
		if($twitterJson === null){
			return false;
		}
		return $twitterJson;
	}
}
?>
